{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### US Equity market performance from 1995 to 2020\n",
    "In this visualization we'll look S&P 500 Index performance from 1995 to 2020. The visulization consists of two charts:\n",
    "* Time Series Chart of Index prices\n",
    "* Histogram of the log returns\n",
    "\n",
    "We'll use the [Fast Interval Selector](../Interactions/Selectors.ipynb) to quickly select different time slices and perform time series analysis on the selected slice (in this case, displaying the total return and the distribution of log returns). **Click on the time series chart to activate the interval selector!**\n",
    "\n",
    "Fun things to try:\n",
    "1. `FastIntervalSelector` responds to mouse moves! Move the mouse pointer up to expand the interval, down to contract the interval. Single click toggles between freezing/unfreezing the window length. Double click totally freezes the interval selector. Move the interval selector to perform quick visual time series analysis!\n",
    "2. Notice that the color of the return label changes with the sign of the total return (red for negative returns and green for positive returns)\n",
    "3. What was the index performance from 1995-2005? 2000-2010? 2010-2020?\n",
    "4. Does the return distribution have fat tails? (especially during 2008 financial crisis, 2020 covid crisis)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "\n",
    "import ipywidgets as widgets\n",
    "from bqplot import DateScale, LinearScale\n",
    "import bqplot.pyplot as plt\n",
    "from bqplot.interacts import FastIntervalSelector"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "format_date = lambda d: d.strftime('%m/%d/%Y')\n",
    "\n",
    "spx_prices = pd.read_csv('spx_prices.csv', index_col=0, parse_dates=True, squeeze=True)\n",
    "log_returns = np.log(spx_prices / spx_prices.shift(1))\n",
    "dates = spx_prices.index"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "fig_title_tmpl = 'S&P Index Prices (from {start} to {end})'\n",
    "fig_title = fig_title_tmpl.format(start=format_date(dates[0]), \n",
    "                                  end=format_date(dates[-1]))\n",
    "time_series_fig = plt.figure(title=fig_title,\n",
    "                             layout=widgets.Layout(width='1300px', height='500px'))\n",
    "\n",
    "plt.scales(scales={'x': DateScale()})\n",
    "axes_options = {'y': {'tick_format': ','}}\n",
    "time_series = plt.plot(dates, spx_prices, colors=['dodgerblue'], \n",
    "                       stroke_width=1.5, axes_options=axes_options)\n",
    "return_label = plt.label([], x=[], y=[spx_prices.max() * .9], \n",
    "                         align='middle', default_size=36, \n",
    "                         font_weight='bolder', colors=['green'])\n",
    "trend_line = plt.plot([], [])\n",
    "intsel = FastIntervalSelector(scale=time_series.scales['x'], marks=[time_series])\n",
    "time_series_fig.interaction = intsel\n",
    "\n",
    "hist_fig = plt.figure(title='Histogram Of Returns',\n",
    "                      layout=widgets.Layout(width='900px',\n",
    "                                            height='450px',\n",
    "                                            margin='0px 150px 0px 150px'))\n",
    "plt.scales(scales={'x': LinearScale(min=-.1, max=.1)})\n",
    "hist = plt.hist(log_returns, colors=['salmon'], bins=75)\n",
    "for axis in hist_fig.axes:\n",
    "    axis.grid_lines = 'none'\n",
    "    if axis.orientation != 'vertical':\n",
    "        axis.tick_format = '.0%'\n",
    "\n",
    "def update_hist(*args):\n",
    "    selected_ix = time_series.selected\n",
    "    if selected_ix is not None:\n",
    "        s, e = selected_ix[0], selected_ix[-1]\n",
    "        spx_prices_slice = spx_prices[s:e]\n",
    "        pct_return = spx_prices[e] / spx_prices[s] - 1\n",
    "        \n",
    "        # update the position of the total return label\n",
    "        with return_label.hold_sync():\n",
    "            return_label.text = ['{:.0%}'.format(pct_return)]\n",
    "            return_label.x = [time_series.x[(s + e) // 2]]\n",
    "            return_label.colors = ['red'] if pct_return < 0. else ['green']\n",
    "        \n",
    "        time_series_fig.title = fig_title_tmpl.format(start=format_date(dates[s]),\n",
    "                                                      end=format_date(dates[e]))\n",
    "        # update hist with returns\n",
    "        hist.sample = np.log(spx_prices_slice / spx_prices_slice.shift(1))\n",
    "\n",
    "time_series.observe(update_hist, 'selected')\n",
    "widgets.VBox([time_series_fig, hist_fig])"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
